﻿using System;
using System.Collections.Generic;
using System.Collections;

namespace Gencode.Controls.Harmonica
{
	
	public class HarmonicaNodeCollection : IList, ICollection, IEnumerable
	{
		HarmonicaNode[] nodes;
		Harmonica harmonica;

		public HarmonicaNodeCollection(Harmonica harmonica)
		{
			this.harmonica = harmonica;
		}

		private void AddEmptyNodeToList()
		{
			if (nodes == null)
				nodes = new HarmonicaNode[0];

			HarmonicaNode[] tmp = new HarmonicaNode[nodes.Length +1];

			for (int i = 0; i < nodes.Length; i++)
				tmp[i] = nodes[i];
			
			nodes = tmp;
		}

		#region IList Members

		public virtual int Add(HarmonicaNode value)
		{
			if (value != null)
			{
				AddEmptyNodeToList();

				nodes[nodes.Length - 1] = value;// as HarmonicaNode;

				if (harmonica != null)
				{
					nodes[nodes.Length - 1].NodeButton.Size = new System.Drawing.Size(harmonica.Width, 20);
					nodes[nodes.Length - 1].NodeButton.Location = new System.Drawing.Point(0, (nodes.Length - 1) * 20);

					harmonica.Controls.Add(nodes[nodes.Length - 1]);
				}
			}
			if (nodes == null)
				return 0;

			return nodes.Length;
		}

		public virtual int AddRange(HarmonicaNode[] range)
		{
			if (range != null && range.Length > 0)
			{
				for (int i = 0; i < range.Length; i++)
				{
					if (range[i] != null)
					{
						AddEmptyNodeToList();

						nodes[nodes.Length - 1] = range[i];// as HarmonicaNode;
						if (harmonica != null)
						{
							nodes[nodes.Length - 1].NodeButton.Size = new System.Drawing.Size(harmonica.Width, 20);
							nodes[nodes.Length - 1].NodeButton.Location = new System.Drawing.Point(0, (nodes.Length - 1) * 20);

							harmonica.Controls.Add(nodes[nodes.Length - 1]);
						}
					}
				}
			}

			if (nodes == null)
				return 0;

			return nodes.Length;
		}

		public void Clear()
		{
			nodes = new HarmonicaNode[0];
		}

		public virtual bool Contains(HarmonicaNode value)
		{
			bool containsNode = false;
			if (nodes != null && nodes.Length > 0)
			{
				for (int i = 0; i < nodes.Length; i++)
				{
					if (nodes[i] == value as HarmonicaNode)
						containsNode = true;
				}
			}
			return containsNode;
		}

		public virtual int IndexOf(HarmonicaNode value)
		{
			int index = -1;
			if (nodes != null && nodes.Length > 0)
			{
				for (int i = 0; i < nodes.Length; i++)
				{
					if (nodes[i] == value as HarmonicaNode)
						index = i;
				}
			}
			return index;
		}

		public virtual void Insert(int index, HarmonicaNode value)
		{
			if (value != null && value is HarmonicaNode)
			{
				if (nodes == null)
					nodes = new HarmonicaNode[1];

				HarmonicaNode[] tmp = new HarmonicaNode[nodes.Length];

				int nIndex = 0;
				for (int i = 0; i < nodes.Length; i++)
				{
					if (index == i)
						tmp[i] = value as HarmonicaNode;
					else
					{
						tmp[i] = nodes[nIndex];
						nIndex++;
					}
				}

				nodes = tmp;
			}
			else
				throw new Exception("Value type is not of type HarmonicaNode.");
		}

		public bool IsFixedSize
		{
			get { return false; }
		}

		public bool IsReadOnly
		{
			get { return false; }
		}

		public virtual void Remove(HarmonicaNode value)
		{
			if (nodes != null && nodes.Length >= 1)
			{
				HarmonicaNode[] tmp = new HarmonicaNode[nodes.Length - 1];
				int tmpIndex = 0;
				for (int i = 0; i < nodes.Length; ++i)
				{
					if (nodes[i] != value)
					{
						tmp[tmpIndex] = nodes[i];
						tmpIndex++;
					}
				}
			}
			else
				throw new Exception("List is empty.");
		}

		public void RemoveAt(int index)
		{
			if ((IsReadOnly) || (IsFixedSize))
			{
				throw new NotSupportedException("List " +
				  "is either read-only or a fixed size.");
			}

			if (nodes != null && nodes.Length >= 1)
			{
				if ((nodes.Length - 1) < index)
					throw new ArgumentOutOfRangeException("Index is out of range.");

				HarmonicaNode[] tmp = new HarmonicaNode[nodes.Length - 1];
				int tmpIndex = 0;
				for (int i = 0; i < nodes.Length; ++i)
				{
					if (i != index)
					{
						tmp[tmpIndex] = nodes[i];
						tmpIndex++;
					}
				}
			}
			else
				throw new Exception("List is empty.");
		}

		public virtual HarmonicaNode this[int index]
		{
			get
			{
				return nodes[index];
			}
			set
			{
				nodes[index] = value as HarmonicaNode;
			}
		}

		#endregion

		#region ICollection Members

		/// <summary>
		/// copys the list to array starting at index
		/// </summary>
		/// <param name="array"></param>
		/// <param name="index"></param>
		public void CopyTo(Array array, int index)
		{
			if (nodes != null)
			{
				if (index < 0 || index >= nodes.Length)
					throw new ArgumentOutOfRangeException("The index is out of range.");
				if (array.Length < (this.Count - index) + 1)
					throw new ArgumentException("Array cannot hold all values.");

				int i = 0;
				for (; index < nodes.Length; index++)
				{
					array.SetValue(nodes[index], i);
					i++;
				}
			}
			else
				throw new Exception("No nodes avaliabel.");
		}

		public int Count
		{
			get
			{
				if (nodes == null)
					return 0;
				return nodes.Length;
			}
		}

		public bool IsSynchronized
		{
			get { throw new NotImplementedException(); }
		}

		public HarmonicaNode SyncRoot
		{
			get { throw new NotImplementedException(); }
		}

		#endregion

		#region IEnumerable Members

		public IEnumerator GetEnumerator()
		{
			return new HarmonicaEnumerator(this);
		}

		#endregion

		#region IList Members

		int IList.Add(object value)
		{
			if (value != null && value is HarmonicaNode)
			{
				return Add((HarmonicaNode)value);
			}
			return 0;
		}

		//void IList.Clear()
		//{
		//    throw new NotImplementedException();
		//}

		bool IList.Contains(object value)
		{
			if (value != null && value is HarmonicaNode)
			{
				return Contains((HarmonicaNode)value);
			}
			return false;
		}

		int IList.IndexOf(object value)
		{
			if (value != null && value is HarmonicaNode)
			{
				return IndexOf((HarmonicaNode)value);
			}
			return -1;
		}

		void IList.Insert(int index, object value)
		{
			if (value != null && value is HarmonicaNode)
			{
				Insert(index, (HarmonicaNode)value);
			}
		}

		void IList.Remove(object value)
		{
			if (value != null && value is HarmonicaNode)
			{
				Remove((HarmonicaNode)value);
			}
		}

		object IList.this[int index]
		{
			get
			{
				return this[index];
			}
			set
			{
				if (value != null && value is HarmonicaNode)
				{
					this[index] = (HarmonicaNode)value;
				}
			}
		}

		#endregion

		#region ICollection Members

		object ICollection.SyncRoot
		{
			get
			{
				return SyncRoot;
			}
		}

		#endregion
	}
}
